package com.molichuxing.gateway.bff.order.services.impl;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.EmailUtil;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.gateway.bff.order.convertor.Convert;
import com.molichuxing.gateway.bff.order.entity.response.OrderOverdueVo;
import com.molichuxing.gateway.bff.order.entity.response.OrderRepaymentVo;
import com.molichuxing.gateway.bff.order.services.OrderDownloadBffService;
import com.molichuxing.gateway.utils.PoiExcelUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;
import com.molichuxing.services.infrastructure.dto.response.OrderScheduleCurrentPeriodDto;
import com.molichuxing.services.infrastructure.dto.response.OrderScheduleOverdueDto;
import com.molichuxing.services.infrastructure.dto.response.UserDto;
import com.molichuxing.services.infrastructure.service.OrderScheduleService;
import com.molichuxing.services.infrastructure.service.UserService;

/**
 * 订单导出bff
 * 
 * @author zoumingyu
 * @date 2019年12月13日
 *
 */
@Service("orderDownloadBffService")
public class OrderDownloadBffServiceImpl implements OrderDownloadBffService {
	private static final Logger logger = LoggerFactory.getLogger(OrderDownloadBffServiceImpl.class);

	@Value("${email_account}")
	private String EMAIL_ACCOUNT;

	@Value("${email_password}")
	private String EMAIL_PASSWORD;

	@Resource
	private OrderScheduleService orderScheduleService;

	@Resource
	private UserService userService;

	/**
	 * 查询专属里程本期还款计划导出数据
	 * 
	 * @param selectParams
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<OrderRepaymentVo> getOrderExclusivelCurrentPeriodDownload(Map<String, Object> selectParams)
			throws Exception {
		List<OrderRepaymentVo> result = null;
		if (!periodSelectParams(selectParams)) {
			return result;
		}
		// 获取本期还款排期信息
		List<OrderScheduleCurrentPeriodDto> currentPeriods = orderScheduleService
				.getExclusivelOrderCurrentPeriodDownload(selectParams);

		if (currentPeriods == null || currentPeriods.isEmpty()) {
			return result;
		}
		result = new ArrayList<>(currentPeriods.size());
		// 用户id集合
		List<Integer> userIds = new ArrayList<>();
		for (OrderScheduleCurrentPeriodDto currentPeriod : currentPeriods) {
			userIds.add(currentPeriod.getUserId());
			result.add(Convert.toOrderRepaymentVo(currentPeriod));
		}
		// 查询用户
		Map<Integer, UserDto> userMap = userService.getUsers(userIds);

		for (OrderRepaymentVo orderRepaymentVo : result) {
			// 用户
			UserDto userDto = userMap == null ? null
					: userMap.isEmpty() ? null : userMap.get(orderRepaymentVo.getUserId());
			// 用户手机号
			orderRepaymentVo.setUserPhone(userDto == null ? null : userDto.getPhone());
			// 用户姓名
			orderRepaymentVo.setUserRealName(userDto == null ? null : userDto.getRealName());
		}

		return result;
	}

	/**
	 * 查询专属里程本期还款计划导出数据条数
	 * 
	 * @param selectParams
	 * @return
	 * @throws Exception
	 */
	@Override
	public Long getOrderExclusivelCurrentPeriodDownloadCount(Map<String, Object> selectParams) throws Exception {
		if (!periodSelectParams(selectParams)) {
			return 0L;
		}
		// 查询条数
		return orderScheduleService.getExclusivelOrderCurrentPeriodDownloadCount(selectParams);
	}

	/**
	 * 异步发送专属里程本期还款计划导出数据
	 * 
	 * @param selectParams
	 * @param user
	 * @throws Exception
	 */
	@Async
	@Override
	public Boolean getOrderExclusivelCurrentPeriodDownloadEmail(Map<String, Object> selectParams, UserEntity user)
			throws Exception {
		List<OrderRepaymentVo> datas = this.getOrderExclusivelCurrentPeriodDownload(selectParams);

		String fileName = "专属订单还款计划(" + DateUtil.formatDate(LocalDate.now()) + ")";

		// 生成excel
		XSSFWorkbook xssBook = PoiExcelUtil.repaymentSchedule(datas);
		// 发送邮件
		EmailUtil.sendMail(EMAIL_ACCOUNT, EMAIL_PASSWORD, fileName, fileName, user.getAccount(), fileName + ".xlsx",
				xssBook);
		return true;
	}

	/**
	 * 查询专属里程订单逾期未还导出数据
	 * 
	 * @param selectParams
	 * @return
	 */
	@Override
	public List<OrderOverdueVo> getExclusivelOrderOverdueDownload(Map<String, Object> selectParams) {
		List<OrderOverdueVo> result = null;
		if (!periodSelectParams(selectParams)) {
			return result;
		}
		// 获取逾期数据导出数据
		List<OrderScheduleOverdueDto> overduePeriods = orderScheduleService
				.getExclusivelOrderOverdueDownload(selectParams);

		if (overduePeriods == null || overduePeriods.isEmpty()) {
			return result;
		}
		result = new ArrayList<>(overduePeriods.size());
		// 用户id集合
		List<Integer> userIds = new ArrayList<>();
		for (OrderScheduleOverdueDto overduePeriod : overduePeriods) {
			userIds.add(overduePeriod.getUserId());
			result.add(Convert.toOrderOverdueVo(overduePeriod));
		}
		// 查询用户
		Map<Integer, UserDto> userMap = userService.getUsers(userIds);

		for (OrderOverdueVo orderOverdueVo : result) {
			// 用户
			UserDto userDto = userMap == null ? null
					: userMap.isEmpty() ? null : userMap.get(orderOverdueVo.getUserId());
			// 用户手机号
			orderOverdueVo.setUserPhone(userDto == null ? null : userDto.getPhone());
			// 用户姓名
			orderOverdueVo.setUserRealName(userDto == null ? null : userDto.getRealName());
		}

		return result;
	}

	/**
	 * 查询专属里程订单逾期未还导出数据条数
	 * 
	 * @param selectParams
	 * @return
	 * @throws Exception
	 */
	@Override
	public Long getOrderExclusivelOverdueDownloadCount(Map<String, Object> selectParams) throws Exception {
		if (!periodSelectParams(selectParams)) {
			return 0L;
		}
		// 查询条数
		return orderScheduleService.getExclusivelOrderOverdueDownloadCount(selectParams);
	}

	/**
	 * 异步发送专属里程订单逾期未还导出数据
	 * 
	 * @param selectParams
	 * @param user
	 * @throws Exception
	 */
	@Async
	@Override
	public Boolean getOrderExclusivelOverdueDownloadEmail(Map<String, Object> selectParams, UserEntity user)
			throws Exception {
		List<OrderOverdueVo> datas = this.getExclusivelOrderOverdueDownload(selectParams);

		String fileName = "专属订单逾期未还排期(" + DateUtil.formatDate(LocalDate.now()) + ")";

		// 生成excel
		XSSFWorkbook xssBook = PoiExcelUtil.overdueSchedule(datas);
		// 发送邮件
		EmailUtil.sendMail(EMAIL_ACCOUNT, EMAIL_PASSWORD, fileName, fileName, user.getAccount(), fileName + ".xlsx",
				xssBook);
		return true;
	}

	private boolean periodSelectParams(Map<String, Object> selectParams) {
		selectParams.put("nowDate", LocalDate.now());
		String orderCodes = ObjectCastUtil.castString(selectParams.get("orderCodes"));
		if (StringUtils.isNotBlank(orderCodes)) {
			// 选择导出
			selectParams.remove("orderCode");
			selectParams.remove("userRealName");
			selectParams.remove("userPhone");
			selectParams.put("orderCodes", Arrays.asList(orderCodes.split(",")));
		}
		// 判断查询条件是否有用户信息
		if (StringUtils.isNotBlank(ObjectCastUtil.castString(selectParams.get("userRealName")))
				|| StringUtils.isNotBlank(ObjectCastUtil.castString(selectParams.get("userPhone")))) {
			// 查询用户ids
			List<Integer> userIdList = getUserIds(ObjectCastUtil.castString(selectParams.get("userRealName")),
					ObjectCastUtil.castString(selectParams.get("userPhone")));
			if (userIdList == null || userIdList.size() <= 0) {
				// 用户不存在
				return false;
			}
			selectParams.put("userIds", userIdList);
			selectParams.remove("userRealName");
			selectParams.remove("userPhone");
		}

		return true;
	}

	/**
	 * 根据用户姓名和手机号查询用户ids
	 * 
	 * @param userRealName
	 *            用户姓名
	 * @param userPhone
	 *            用户手机号
	 * @return
	 */
	private List<Integer> getUserIds(String userRealName, String userPhone) {
		List<Integer> result = null;
		// 查询用信息
		List<UserDto> userDtoList = userService.getUserList(null, userRealName, userPhone);
		if (userDtoList == null || userDtoList.isEmpty()) {
			// 用户不存在
			return result;
		}
		result = new ArrayList<>();
		for (UserDto userDto : userDtoList) {
			result.add(userDto.getId());
		}

		return result;
	}
}
